/**
 ******************************************************************************
 * @file           : bsp_usart.c
 * @brief          : USART Driver Implementation (STM32F4xx)
 ******************************************************************************
 * @attention
 *
 * USART驱动实现文件
 * 使用GPIO AF复用功能，中断接收，环形缓冲区
 *
 ******************************************************************************
 */

/* Includes ------------------------------------------------------------------*/
#include "./BSP/USART/bsp_usart.h"
#include "./BSP/USART/bsp_usart_config.h"
#include <stdio.h>
#include <stdarg.h>
#include <string.h>

/* Private includes ----------------------------------------------------------*/
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
static UART_HandleTypeDef sg_usart_handle;
static volatile USART_State_e sg_usart_state = USART_STATE_IDLE;  /*!< USART当前状态 */

/* 接收缓冲区（环形缓冲区） */
static uint8_t sg_rx_buffer[USART_RX_BUF_SIZE];
static volatile uint16_t sg_rx_write_index = 0;
static volatile uint16_t sg_rx_read_index = 0;
static volatile uint16_t sg_rx_count = 0;

/* Private function prototypes -----------------------------------------------*/
static void usart_gpio_init(void);

/* Private functions ---------------------------------------------------------*/

/**
 * @brief       USART GPIO初始化
 *
 * @param       无
 *
 * @retval      无
 *
 * @note        STM32F4xx使用GPIO AF复用功能
 */
static void usart_gpio_init(void)
{
    GPIO_InitTypeDef gpio_init_struct = {0};

    /* 使能GPIO时钟 */
    USART_TX_GPIO_CLK_ENABLE();
    USART_RX_GPIO_CLK_ENABLE();

    /* 配置TX引脚（复用推挽输出） */
    gpio_init_struct.Pin = USART_TX_GPIO_PIN;
    gpio_init_struct.Mode = GPIO_MODE_AF_PP;
    gpio_init_struct.Pull = GPIO_PULLUP;
    gpio_init_struct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    gpio_init_struct.Alternate = USART_GPIO_AF;  /* 配置AF功能 */
    HAL_GPIO_Init(USART_TX_GPIO_PORT, &gpio_init_struct);

    /* 配置RX引脚（复用推挽输入） */
    gpio_init_struct.Pin = USART_RX_GPIO_PIN;
    gpio_init_struct.Mode = GPIO_MODE_AF_PP;
    gpio_init_struct.Pull = GPIO_PULLUP;
    gpio_init_struct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    gpio_init_struct.Alternate = USART_GPIO_AF;  /* 配置AF功能 */
    HAL_GPIO_Init(USART_RX_GPIO_PORT, &gpio_init_struct);
}

/* Exported functions --------------------------------------------------------*/

/**
 * @brief       USART初始化
 *
 * @param[in]   baudrate 波特率
 *
 * @retval      无
 *
 * @note        配置为8位数据，1位停止位，无校验
 */
void usart_init(uint32_t baudrate)
{
    /* 使能USART时钟 */
    USART_UARTx_CLK_ENABLE();

    /* 初始化GPIO */
    usart_gpio_init();

    /* 配置USART */
    sg_usart_handle.Instance = USART_UARTx;
    sg_usart_handle.Init.BaudRate = baudrate;
    sg_usart_handle.Init.WordLength = UART_WORDLENGTH_8B;
    sg_usart_handle.Init.StopBits = UART_STOPBITS_1;
    sg_usart_handle.Init.Parity = UART_PARITY_NONE;
    sg_usart_handle.Init.Mode = UART_MODE_TX_RX;
    sg_usart_handle.Init.HwFlowCtl = UART_HWCONTROL_NONE;
    sg_usart_handle.Init.OverSampling = UART_OVERSAMPLING_16;

    if (HAL_UART_Init(&sg_usart_handle) != HAL_OK)
    {
        log_e("USART initialization failed");
        return;
    }

    /* 配置中断优先级并使能 */
    HAL_NVIC_SetPriority(USART_UARTx_IRQn, 3, 0);
    HAL_NVIC_EnableIRQ(USART_UARTx_IRQn);

    /* 使能接收中断 */
    __HAL_UART_ENABLE_IT(&sg_usart_handle, UART_IT_RXNE);

    /* 清空接收缓冲区 */
    sg_rx_write_index = 0;
    sg_rx_read_index = 0;
    sg_rx_count = 0;
    
    /* 设置空闲状态 */
    sg_usart_state = USART_STATE_IDLE;

    log_i("USART%d initialized: %u baud", USART_SELECT_NUM, baudrate);
}

/**
 * @brief       USART去初始化
 *
 * @param       无
 *
 * @retval      无
 */
void usart_deinit(void)
{
    /* 禁用中断 */
    HAL_NVIC_DisableIRQ(USART_UARTx_IRQn);

    /* 去初始化USART */
    HAL_UART_DeInit(&sg_usart_handle);

    log_i("USART%d deinitialized", USART_SELECT_NUM);
}

/**
 * @brief       发送单个字节
 *
 * @param[in]   data 要发送的字节
 *
 * @retval      无
 */
void usart_send_byte(uint8_t data)
{
    HAL_UART_Transmit(&sg_usart_handle, &data, 1, HAL_MAX_DELAY);
}

/**
 * @brief       发送多个字节
 *
 * @param[in]   buf 数据缓冲区
 * @param[in]   len 数据长度
 *
 * @retval      无
 */
void usart_send_bytes(const uint8_t *buf, uint16_t len)
{
    if (buf == NULL || len == 0)
    {
        return;
    }

    HAL_UART_Transmit(&sg_usart_handle, (uint8_t *)buf, len, HAL_MAX_DELAY);
}

/**
 * @brief       发送字符串
 *
 * @param[in]   str 字符串
 *
 * @retval      无
 */
void usart_send_string(const char *str)
{
    if (str == NULL)
    {
        return;
    }

    usart_send_bytes((const uint8_t *)str, strlen(str));
}

/**
 * @brief       格式化输出
 *
 * @param[in]   format 格式化字符串
 * @param[in]   ... 可变参数
 *
 * @retval      无
 *
 * @note        类似printf，最大支持256字节
 */
void usart_printf(const char *format, ...)
{
    char buf[256];
    va_list args;

    va_start(args, format);
    vsnprintf(buf, sizeof(buf), format, args);
    va_end(args);

    usart_send_string(buf);
}

/**
 * @brief       获取接收缓冲区数据量
 *
 * @param       无
 *
 * @retval      缓冲区中的字节数
 */
uint16_t usart_get_rx_count(void)
{
    return sg_rx_count;
}

/**
 * @brief       读取单个字节
 *
 * @param       无
 *
 * @retval      读取的字节（无数据返回0）
 */
uint8_t usart_read_byte(void)
{
    uint8_t data = 0;

    if (sg_rx_count > 0)
    {
        data = sg_rx_buffer[sg_rx_read_index];
        sg_rx_read_index = (sg_rx_read_index + 1) % USART_RX_BUF_SIZE;
        sg_rx_count--;
    }

    return data;
}

/**
 * @brief       读取多个字节
 *
 * @param[out]  buf 数据缓冲区
 * @param[in]   len 要读取的长度
 *
 * @retval      实际读取的字节数
 */
uint16_t usart_read_bytes(uint8_t *buf, uint16_t len)
{
    uint16_t i;
    uint16_t count = 0;

    if (buf == NULL || len == 0)
    {
        return 0;
    }

    for (i = 0; i < len && sg_rx_count > 0; i++)
    {
        buf[i] = usart_read_byte();
        count++;
    }

    return count;
}

/**
 * @brief       清空接收缓冲区
 *
 * @param       无
 *
 * @retval      无
 */
void usart_flush_rx_buffer(void)
{
    sg_rx_write_index = 0;
    sg_rx_read_index = 0;
    sg_rx_count = 0;
}

/**
 * @brief       USART中断服务函数
 *
 * @param       无
 *
 * @retval      无
 *
 * @note        在stm32f4xx_it.c中调用此函数
 */
void USARTx_IRQHandler(void)
{
    uint8_t data;

    /* 接收中断 */
    if (__HAL_UART_GET_FLAG(&sg_usart_handle, UART_FLAG_RXNE) != RESET)
    {
        /* 读取数据 */
        data = (uint8_t)(sg_usart_handle.Instance->DR & 0xFF);

        /* 写入环形缓冲区 */
        if (sg_rx_count < USART_RX_BUF_SIZE)
        {
            sg_rx_buffer[sg_rx_write_index] = data;
            sg_rx_write_index = (sg_rx_write_index + 1) % USART_RX_BUF_SIZE;
            sg_rx_count++;
        }
        else
        {
            /* 缓冲区满，丢弃最旧的数据 */
            sg_rx_read_index = (sg_rx_read_index + 1) % USART_RX_BUF_SIZE;
            sg_rx_buffer[sg_rx_write_index] = data;
            sg_rx_write_index = (sg_rx_write_index + 1) % USART_RX_BUF_SIZE;
        }

        /* 清除接收标志 */
        __HAL_UART_CLEAR_FLAG(&sg_usart_handle, UART_FLAG_RXNE);
    }

    /* 溢出错误处理 */
    if (__HAL_UART_GET_FLAG(&sg_usart_handle, UART_FLAG_ORE) != RESET)
    {
        __HAL_UART_CLEAR_OREFLAG(&sg_usart_handle);
    }
}

/**
 * @brief       获取USART状态
 *
 * @param       无
 *
 * @retval      USART_STATE_IDLE - 空闲
 * @retval      USART_STATE_TX - 发送中
 * @retval      USART_STATE_RX - 接收中
 * @retval      USART_STATE_ERROR - 错误
 */
USART_State_e usart_get_state(void)
{
    return sg_usart_state;
}

/**
 * @brief       检查是否有接收数据
 *
 * @param       无
 *
 * @retval      1 - 有数据
 * @retval      0 - 无数据
 */
uint8_t usart_is_rx_ready(void)
{
    return (sg_rx_count > 0) ? 1 : 0;
}

/**
 * @brief       检查是否有完整行数据（以\r\n结尾）
 *
 * @param       无
 *
 * @retval      1 - 有完整行
 * @retval      0 - 无完整行
 */
uint8_t usart_is_line_ready(void)
{
    uint16_t i;
    
    /* 查找\r\n */
    for (i = 0; i < sg_rx_count - 1; i++)
    {
        uint16_t idx = (sg_rx_read_index + i) % USART_RX_BUF_SIZE;
        uint16_t idx_next = (sg_rx_read_index + i + 1) % USART_RX_BUF_SIZE;
        
        if (sg_rx_buffer[idx] == '\r' && sg_rx_buffer[idx_next] == '\n')
        {
            return 1;
        }
    }
    
    return 0;
}

/**
 * @brief       打印USART状态（调试接口）
 *
 * @param       无
 *
 * @retval      无
 */
void usart_print_status(void)
{
    const char *state_str[] = {
        "IDLE",
        "TX",
        "RX",
        "ERROR"
    };
    
    if (sg_usart_state < 4)
    {
        log_i("USART State: %s", state_str[sg_usart_state]);
    }
    else
    {
        log_i("USART State: UNKNOWN");
    }
    
    log_i("RX Count: %d", sg_rx_count);
    log_i("RX Ready: %s", usart_is_rx_ready() ? "YES" : "NO");
    log_i("Line Ready: %s", usart_is_line_ready() ? "YES" : "NO");
}

/**
 * @brief       重定向printf到USART
 *
 * @param[in]   ch 要输出的字符
 * @param[in]   f 文件指针（未使用）
 *
 * @retval      输出的字符
 *
 * @note        使能半主机模式时注释掉此函数
 */
#if defined(__GNUC__) && !defined(__clang__)
    /* GCC */
    int _write(int fd, char *ptr, int len)
    {
        (void)fd;
        usart_send_bytes((const uint8_t *)ptr, len);
        return len;
    }
#elif defined(__CC_ARM) || defined(__ARMCC_VERSION)
    /* Keil MDK */
    int fputc(int ch, FILE *f)
    {
        (void)f;
        usart_send_byte((uint8_t)ch);
        return ch;
    }
#elif defined(__ICCARM__)
    /* IAR */
    #include <LowLevelIOInterface.h>
    size_t __write(int handle, const unsigned char *buffer, size_t size)
    {
        (void)handle;
        usart_send_bytes(buffer, size);
        return size;
    }
#endif
